﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using dotUML.Core.Common.SequenceDiagram;

namespace dotUML.Core.Common
{
    /// <summary>
    /// ISequenceDiagram defines the interface of a UML sequence diagram.
    /// </summary>
    public interface ISequenceDiagram : IDiagram
    {
        /// <summary>
        /// Create a lifeline and add it to the current UML sequence diagram.
        /// Throws an error if an element with the provided name already exists.
        /// </summary>
        /// <param name="Name">Lifeline name.</param>
        /// <param name="LifelineType">Lifeline type.</param>
        /// <returns>Newly created lifeline.</returns>
        ILifeline AddLifeline(string Name, ELifelineType LifelineType);
        /// <summary>
        /// Get a lifeline.
        /// </summary>
        /// <param name="Name">Lifeline name.</param>
        /// <returns>Required lifeline or null, if it does not exist.</returns>
        ILifeline GetLifeline(string Name);
        /// <summary>
        /// Delete a lifeline. If required lifeline does not exist, does nothing.
        /// </summary>
        /// <param name="Name">Lifeline name.</param>
        void DeleteLifeline(string Name);
        /// <summary>
        /// Collection of lifelines names.
        /// </summary>
        ICollection<string> LifelinesNames
        {
            get;
        }

        /// <summary>
        /// Create a message and add it to the current UML sequence diagram.
        /// Throws an error if an element with the provided name already exists.
        /// </summary>
        /// <param name="Name">Message name.</param>
        /// <param name="MessageType">Message type.</param>
        /// <param name="Source">Source lifeline.</param>
        /// <param name="Target">Target lifeline.</param>
        /// <param name="Async">Synchronism of the message.</param>
        /// <param name="Label">Message lable.</param>
        /// <returns>Newly created message.</returns>
        IMessage AddMessage(string Name, EMessageType MessageType, string Source, string Target, bool Async, string Label);
        /// <summary>
        /// Get a message.
        /// </summary>
        /// <param name="Name">Message name.</param>
        /// <returns>Requered message or null, if it does not exist.</returns>
        IMessage GetMessage(string Name);
        /// <summary>
        /// Delete a message. If required message does not exist, does nothing.
        /// </summary>
        /// <param name="Name">Message name.</param>
        void DeleteMessage(string Name);

        /// <summary>
        /// Create a constraint and add it to the current UML sequence diagram.
        /// Throws an error if an element with the provided name already exists.
        /// </summary>
        /// <param name="Name">Constraint name.</param>
        /// <param name="ConstraintType">Constraint type.</param>
        /// <param name="Value">Constraint value.</param>
        /// <param name="MessageName">Name of constrained message.</param>
        /// <returns>Newly created constraint.</returns>
        IConstraint AddConstraint(string Name, EConstraintType ConstraintType, string Value, string MessageName);
        /// <summary>
        /// Get a constraint.
        /// </summary>
        /// <param name="Name">Constraint name.</param>
        /// <returns>Required constraint or null, if it does not exist.</returns>
        IConstraint GetConstraint(string Name);
        /// <summary>
        /// Delete a constraint. If required constraint does not exist, does nothing.
        /// </summary>
        /// <param name="Name">Constraint name.</param>
        void DeleteConstraint(string Name);

        /// <summary>
        /// Create a combined fragment and add it to the current UML sequence diagram.
        /// Throws an error if an element with the provided name already exists.
        /// </summary>
        /// <param name="Name">Combined fragment name.</param>
        /// <param name="CombinedFragmentType">Combined fragment type.</param>
        /// <returns>Newly created combined fragment.</returns>
        ICombinedFragmentBase AddCombinedFragment(string Name, ECombinedFragmentType CombinedFragmentType);
        /// <summary>
        /// Get a combined fragment.
        /// </summary>
        /// <param name="Name">Combined fragment name.</param>
        /// <returns>Required combined fragment or null, if it does not exist.</returns>
        ICombinedFragmentBase GetCombinedFragment(string Name);
        /// <summary>
        /// Delete a combined fragment. If required combined fragment does not exist, does nothing.
        /// </summary>
        /// <param name="Name">Combined fragment name.</param>
        void DeleteCombinedFragment(string Name);

        /// <summary>
        /// Create an invariant and add it to the current UML sequence diagram.
        /// Throws an error if an element with the provided name already exists.
        /// </summary>
        /// <param name="Name">Invariant name.</param>
        /// <param name="LifelineName">Lifeline of the invariant.</param>
        /// <returns>Newly created invariant.</returns>
        IInvariant AddInvariant(string Name, string LifelineName);
        /// <summary>
        /// Get an invariant.
        /// </summary>
        /// <param name="Name">Invariant name.</param>
        /// <returns>Required invariant or null, if it does not exist.</returns>
        IInvariant GetInvariant(string Name);
        /// <summary>
        /// Delete an invariant. If required invariant does not exist, does nothing.
        /// </summary>
        /// <param name="Name">Invariant name.</param>
        void DeleteInvariant(string Name);

        /// <summary>
        /// Create a continuation and add it to the current UML sequence diagram.
        /// Throws an error if an element with the provided name already exists.
        /// </summary>
        /// <param name="Name">Continuation name.</param>
        /// <param name="Value">Continuation value.</param>
        /// <returns>Newly created continuation.</returns>
        IContinuation AddContinuation(string Name, string Value);
        /// <summary>
        /// Get a continuation.
        /// </summary>
        /// <param name="Name">Continuation name.</param>
        /// <returns>Required continuation or null, if it does not exist.</returns>
        IContinuation GetContinuation(string Name);
        /// <summary>
        /// Delete a continuation. If required continuation does not exist, does nothing.
        /// </summary>
        /// <param name="Name">Continuation name.</param>
        void DeleteContinuation(string Name);

        /// <summary>
        /// Create a concurrent and add it to the current UML sequence diagram.
        /// Throws an error if an element with the provided name already exists.
        /// </summary>
        /// <param name="Name">Concurrent name.</param>
        /// <param name="LifelineName">Lifeline of concurrent.</param>
        /// <returns>Newly created concurrent.</returns>
        IConcurrent AddConcurrent(string Name, string LifelineName);
        /// <summary>
        /// Get a concurrent.
        /// </summary>
        /// <param name="Name">Concurrent name.</param>
        /// <returns>Required concurrent or null, if it does not exist.</returns>
        IConcurrent GetConcurrent(string Name);
        /// <summary>
        /// Delete a concurrent. If required concurrent does not exist, does nothing.
        /// </summary>
        /// <param name="Name">Concurrent name.</param>
        void DeleteConcurrent(string Name);

        /// <summary>
        /// Create a reference and add it to the current UML sequence diagram.
        /// Throws an error if an element with the provided name already exists.
        /// </summary>
        /// <param name="Name">Reference name.</param>
        /// <returns>Newly created reference.</returns>
        IReference AddReference(string Name);
        /// <summary>
        /// Get a reference.
        /// </summary>
        /// <param name="Name">Reference name.</param>
        /// <returns>Required reference or null, if it does not exist.</returns>
        IReference GetReference(string Name);
        /// <summary>
        /// Delete a reference. If required reference does not exist, does nothing.
        /// </summary>
        /// <param name="Name">Reference name.</param>
        void DeleteReference(string Name);

        /// <summary>
        /// Create a destruction object and add it to the current UML sequence diagram.
        /// Throws an error if an element with the provided name already exists.
        /// </summary>
        /// <param name="Name">Destruction object name.</param>
        /// <returns>Newly created destruction object.</returns>
        IDestruction AddDestruction(string Name);
        /// <summary>
        /// Get a destruction object.
        /// </summary>
        /// <param name="Name">Destruction object name.</param>
        /// <returns>Required destruction object or null, if it does not exist.</returns>
        IDestruction GetDestruction(string Name);
        /// <summary>
        /// Delete a destruction object. If required destruction object does not exist, does nothing.
        /// </summary>
        /// <param name="Name">Destruction object name.</param>
        void DeleteDestruction(string Name);

        /// <summary>
        /// Add an element to the elements sequence, which defines the order 
        /// of the element's appearance in the sequence diagram.
        /// Throws an error if an element with the provided name already exists.
        /// </summary>
        /// <param name="Name">Element name.</param>
        void AddSequenceEntry(string Name);

        /// <summary>
        /// Assign numbers to messages, base on their position in the sequence.
        /// </summary>
        void NumberMessages();
    }
}
